Prospecção Séries Temporais

G4: Edinaldo de Alencar / Igor Freire / Ramon Araújo / Ricardo Ribeiro

28 de outubro de 2014

Importação da base de dados

Pacote utilizado para leitura em formato de séries temporais:

library(zoo)

Importar as bases de dados utilizando read.zoo:

# A base de dados e os scripts R estão no mesmo diretório (o diretório atual)
setwd(paste("~/Documents/Mestrado/UFPA/Mineração de Dados/data-mining-ppgee/trabalho-2-forecast/", sep=""))

# Inicialmente, ler a base de dados diários como um data frame (através de read.csv)
dataframe_diario <- read.csv(file = "dataset_diario.csv", sep = ";", dec = ",", header = TRUE)
# Em seguida, converter para uma série temporal (lista indexada pela data)
dataset_diario <- zoo(as.matrix(dataframe_diario[, -1:-2]), as.Date(dataframe_diario[,1], format = "%d/%m/%y"))
# Obs: em "format" usa-se y minusculo, pois a data está no formato dd/mm/yy

# A função read.zoo() abaixo não retorna lista com vetores categóricos e numéricos ao mesmo tempo.
# Isto é, se houver dados categóricos e numéricos na base, os numéricos serão convertidos.
# Por isso, a base com dados diários não foi lida diretamente com read.zoo. A base com dados mensais 
# pode ser lida diretamente com read.zoo()
# Ler o .csv como uma série temporal (indexado pela data)
dataset_mensal <- read.zoo(file = "dataset_mensal.csv", sep = ";", dec = ",", header = TRUE, 
        index = 1, tz = "", FUN = as.yearmon, format = "%m/%Y", drop = FALSE)
# index ->  coluna do arquivo .csv que contém a data
# Obs: em "format" usa-se Y maiúsculo, pois a data está no formato mm/yyyy

Notar que é necessário definir:

  1. O caractere que separa as entradas no arquivo .csv (sep =)
  2. O caractere separador de casas decimais do atributo numérico presente nas bases de dados (dec =)

Informação sobre os dias da semana

Observar que a informação sobre os dias da semana é redundante, pois pode ser obtida através de:

dia <- weekdays(index(dataset_diario))

que tem como resultado, por exemplo, para as 10 primeiras amostras da base:

head(dia, 10)
##  [1] "Terça Feira"   "Quarta Feira"  "Quinta Feira"  "Sexta Feira"  
##  [5] "Sábado"        "Domingo"       "Segunda Feira" "Terça Feira"  
##  [9] "Quarta Feira"  "Quinta Feira"

o qual pode ser confirmado comparando com as 10 primeiras entradas na coluna “dia” da base:

head(dataframe_diario[,2], 10)
##  [1] ter qua qui sex sab dom seg ter qua qui
## Levels: dom qua qui sab seg sex ter

Por isso, na leitura da base em dataset_diario, esta coluna foi ignorada.

Inspeção do Conjunto de Dados

summary(dataset_diario)
##      Index            dataset_diario 
##  Min.   :2002-01-01   Min.   :11130  
##  1st Qu.:2004-01-01   1st Qu.:19468  
##  Median :2005-12-31   Median :22811  
##  Mean   :2005-12-31   Mean   :23158  
##  3rd Qu.:2007-12-31   3rd Qu.:26712  
##  Max.   :2009-12-31   Max.   :34292
summary(dataset_mensal)
##      Index          fluxo       
##  Min.   :1992   Min.   :261544  
##  1st Qu.:1996   1st Qu.:408961  
##  Median :2001   Median :529912  
##  Mean   :2001   Mean   :548440  
##  3rd Qu.:2005   3rd Qu.:662250  
##  Max.   :2010   Max.   :982708

Séries Temporais

Conversão dos dados para o formato de série temporal no R.

Série Mensal:

# Frequency --> numero de observações por unidade de tempo 
# define a unidade de tempo (e.g. 12, unidade de tempo = ano)
tsMensal <- ts(dataset_mensal, frequency=12, start=1992)
plot(tsMensal, xlab="Anos", ylab="Fluxo")

plot of chunk unnamed-chunk-8

Série Diária:

Série temporal multi-sazonal

tsDiario <- msts(dataset_diario, seasonal.periods=c(7, 365.25), start=c(2002,1,1))
plot(tsDiario, xlab="Anos", ylab="Fluxo")

plot of chunk unnamed-chunk-9

Decomposição das séries temporais

Decompor a série temporal em:

plot(decompose(tsMensal), xlab="Anos")

plot of chunk unnamed-chunk-10

plot(decompose(tsDiario), xlab="Anos")

plot of chunk unnamed-chunk-10

  1. Clara tendência (trend) de subida.
  2. Sazonalidade de 1 ano.

Objetivos

Realizar prospecções de curto, médio e longo prazo.

Curto Prazo

Para curto prazo, será utilizada a série temporal com dados diários (tsDiario).

Médio Prazo

Longo Prazo

Para médio e longo prazo, será utilizada a série temporal com dados mensais (tsMensal).

Separação dos dados

Separação da séries temporais em em conjuntos de treinamento e conjunto de testes.

Curto Prazo

Separação de tsDiario em conjuntos de treinamento e teste.

30 dias:

tsDiarioTrain <- window(tsDiario, end=(2006-0.01)) # De Jan 2002 até Dez 2005
tsDiarioTest30Days <- window(tsDiario, start=c(2006,1), end=c(2006,30)) # De 1/1/2006 a 30/1/2006

45 dias:

# 45 dias a partir De 1/1/2006
tsDiarioTest45Days <- window(tsDiario, start=c(2006,1), end=c(2006,45)) 

Médio/Longo Prazo

4 meses:

Separação de tsMensal em conjuntos de treinamento e teste:

tsMensalTrain <- window(tsMensal, end=c(2005, 12)) # De Jan 1992 até Dez 2005
tsMensalTest4mth <- window(tsMensal, start=2006, end=c(2006,4)) # De Jan 2006 até Mar 2006

6 meses:

tsMensalTest6mth <- window(tsMensal, start=2006, end=c(2006,6)) # De Jan 2006 até Jun 2006

1 ano:

tsMensalTest1yr <- window(tsMensal, start=2006, end=2007) # De Jan 2006 até Jan 2007

2 anos:

tsMensalTest2yr <- window(tsMensal, start=2006, end=(2008)) # De Jan 2006 até Jan 2008

Acurácia

Métricas comparativas usuais:

Diferentemente do ME, MAE e RMSE, o medidor MAPE é independente da escala.

MAPE:

\[M = \frac{1}{n} \sum \limits_{t=1}^{n} \left| \frac{A_t - F_t}{A_t} \right|,\]

onde \(A_t\) é o valor verdadeiro, \(F_t\) é o valor predito e \(n\) é o número de amostras temporais preditas.

Como desvantagem, o critério MAPE tem comportamento indefinido quando o valor verdadeiro \(A_t=0\) (divisão por zero).

Métodos simplistas

Funções utilizadas na biblioteca forecast:

Estratégia de Avaliação dos Métodos

Apresenta-se a seguir:

Nota:

Pacote utilizado (ver (R. J. Hyndman 2014) e (Leek 2014)):

library(forecast)

Saída: objeto forecast, contendo: * Série Original * Predições * Método utilizado * Intervalos de Predição * Resíduos

Métodos simplistas em prospecções de Curto Prazo

Prospecções através dos métodos simplísticos para um prazo 30 dias.

Série temporal de treinamento

Fluxo diário de Janeiro de 2002 a Dezembro de 2005

# Dados de treinamento
plot(tsDiarioTrain, xlab="Anos", ylab="Fluxo Diário",)
title("Fluxo diário de treinamento: Jan 2002 a Dez 2005")

plot of chunk unnamed-chunk-18

Número de dias para os quais deseja-se prever o fluxo

diasAPrever <- 30

Média

# Média
f_mean <- meanf(tsDiarioTrain, h=diasAPrever)
plot(f_mean, xlab="Anos", ylab="Fluxo Diario", include=365)
lines(tsDiarioTest30Days, col="red")
legend("topleft",legend=c("Real"),col=2,lty=1)

plot of chunk unnamed-chunk-20

# Acurácia
accuracy(f_mean, tsDiarioTest30Days)
##                      ME RMSE  MAE   MPE  MAPE  MASE   ACF1 Theil's U
## Training set -3.993e-13 2462 1998 -1.64 10.48 1.065 0.7647        NA
## Test set      2.701e+03 3138 2818 11.63 12.26 1.502 0.4432     1.797

Naïve

# Naïve
f_naive <- naive(tsDiarioTrain, h=diasAPrever)
plot(f_naive, xlab="Anos", ylab="Fluxo Diario", include=365)
lines(tsDiarioTest30Days, col="red")
legend("topleft",legend=c("Real"),col=2,lty=1)

plot of chunk unnamed-chunk-21

# Acurácia
accuracy(f_naive, tsDiarioTest30Days)
##                    ME RMSE  MAE     MPE  MAPE   MASE    ACF1 Theil's U
## Training set    6.341 1681 1210 -0.3677 6.389 0.6451 -0.1089        NA
## Test set     -876.950 1823 1282 -4.5074 6.186 0.6835  0.4432     1.065

Naïve Sazonal

# Naïve Sazonal
f_seasonal_naive <- snaive(tsDiarioTrain, h=diasAPrever)
plot(f_seasonal_naive, xlab="Anos", ylab="Fluxo Diario", include=365)
lines(tsDiarioTest30Days, col="red")
legend("topleft",legend=c("Real"),col=2,lty=1)

plot of chunk unnamed-chunk-22

# Acurácia
accuracy(f_seasonal_naive, tsDiarioTest30Days)
##                ME RMSE  MAE   MPE  MAPE   MASE   ACF1 Theil's U
## Training set 1579 2415 1876 7.280 9.051 1.0000 0.1346        NA
## Test set     1422 2263 1737 6.088 7.629 0.9259 0.2102     1.399

Drift

# Drift
f_drift <- rwf(tsDiarioTrain, drift = TRUE, h=diasAPrever)
plot(f_drift, xlab="Anos", ylab="Fluxo Diario", include=365)
lines(tsDiarioTest30Days, col="red")
legend("topleft",legend=c("Real"),col=2,lty=1)

plot of chunk unnamed-chunk-23

# Acurácia
accuracy(f_drift, tsDiarioTest30Days)
##                      ME RMSE  MAE     MPE  MAPE   MASE    ACF1 Theil's U
## Training set  1.911e-13 1681 1210 -0.4006 6.391 0.6452 -0.1089        NA
## Test set     -9.847e+02 1859 1287 -4.9862 6.234 0.6863  0.4333     1.088

Métodos simplistas em prospecções de médio prazo

Prospecções através dos métodos simplísticos para um prazo 4 meses.

Série temporal de treinamento

Fluxo mensal de Janeiro de 2002 a Dezembro de 2005

# Dados de treinamento
plot(tsMensalTrain, xlab="Anos", ylab="Fluxo Mensal")
title("Fluxo mensal de treinamento: Jan 2002 a Dez 2005")

plot of chunk unnamed-chunk-24

Número de meses para os quais deseja-se prever o fluxo

mesesAPrever <- 4

Comparação dos métodos simplísticos

plot of chunk unnamed-chunk-26plot of chunk unnamed-chunk-26plot of chunk unnamed-chunk-26plot of chunk unnamed-chunk-26

##               Mean Näive N-Sazonal Drift
## Training set 22.82 4.376     7.673 4.408
## Test set     29.64 5.202     6.735 6.139

Métodos simplistas em prospecções de longo prazo

Prospecções através dos métodos simplísticos para um prazo 1 ano.

Série temporal de treinamento

Fluxo mensal de Janeiro de 2002 a Dezembro de 2005

# Dados de treinamento
plot(tsMensalTrain, xlab="Anos", ylab="Fluxo Mensal")
title("Fluxo mensal de treinamento: Jan 2002 a Dez 2005")

plot of chunk unnamed-chunk-27

Número de meses para os quais deseja-se prever o fluxo

mesesAPrever <- 12

Comparação dos métodos simplísticos

plot of chunk unnamed-chunk-29plot of chunk unnamed-chunk-29plot of chunk unnamed-chunk-29plot of chunk unnamed-chunk-29

##               Mean Näive N-Sazonal Drift
## Training set 22.82 4.376     7.673 4.408
## Test set     34.45 5.524     7.163 4.601

Regressão Linear

30 dias

diasAPrever <- 30
reg <- tslm(tsDiarioTrain ~ trend + season)
regfcast <- forecast(reg, h=diasAPrever)
plot(regfcast, xlab="Anos", ylab="Fluxo Diario", include=365)
lines(tsDiarioTest30Days, col="red")
legend("topleft",legend=c("Real"),col=2,lty=1)

plot of chunk unnamed-chunk-30

accuracy(regfcast, tsDiarioTest30Days)
##                     ME RMSE    MAE     MPE MAPE   MASE   ACF1 Theil's U
## Training set 9.456e-14 1263  985.7 -0.4544 5.26 0.5255 0.2678        NA
## Test set     7.235e+00 1769 1394.2 -0.5195 6.43 0.7432 0.3949     1.041

1 Ano

mesesAPrever <- 12
reg <- tslm(tsMensalTrain ~ trend+season)
regfcast <- forecast(reg, h=mesesAPrever)
accuracy(regfcast, tsMensalTest1yr)
##                      ME  RMSE   MAE     MPE  MAPE   MASE   ACF1 Theil's U
## Training set -1.754e-13 26528 21375 -0.3482 4.503 0.5763 0.9182        NA
## Test set      4.926e+04 55298 49262  6.6054 6.605 1.3281 0.6854      1.27

Modelo ARIMA

ARIMA (auto regressive integration moving average)

Moving-average Modelo médias-móveis

Dado no instante \(t\) de uma série temporal é dado pelo valor esperado da variável aleatória acrescida do ruído branco no instante \(t\) e a soma ponderada do ruído branco em instantes passados.

O número de instantes passados considerados é dado pela ordem do modelo.

Médias móveis de ordem 3:

plot(tsMensalTrain, xlab="Anos", ylab="Fluxo Mensal")
movAvg <- ma(tsMensalTrain, order=3)
lines(movAvg, col="red")

plot of chunk unnamed-chunk-32

Auto-regressive - Modelo auto regressivo (AR)

Dado no instante \(t\) de uma série temporal é expresso como a média ponderada dos dados em instantes passados acrescida de ruído branco.

O número de instantes passados considerados é dado pela ordem do modelo.

ARMA

ARMA: autoregressive moving-average - combinação de ambos

ARIMA

ARIMA: ARMA com um passo de diferenciação

Método ARIMA em prospecções de curto prazo

Para 30 dias

diasAPrever <- 30

Modelo:

arima_model_30days <- auto.arima(tsDiarioTrain)
## Warning: Unable to fit final model using maximum likelihood. AIC value
## approximated

Predição:

fcast_arima_30days <- forecast(arima_model_30days, h=diasAPrever)
plot(fcast_arima_30days, xlab="Anos", ylab="Fluxo Diário")
lines(tsDiarioTest30Days, col="red")

plot of chunk unnamed-chunk-35

Acurácia:

accuracy(fcast_arima_30days, tsDiarioTest30Days)
##                     ME RMSE    MAE     MPE  MAPE   MASE     ACF1 Theil's U
## Training set     1.499 1122  901.4 -0.3162 4.745 0.4805 -0.01943        NA
## Test set     -1182.930 1886 1563.8 -5.7830 7.367 0.8336  0.54952     1.103

Método ARIMA em prospecções de médio prazo

Para 4 meses

mesesAPrever <- 4

Modelo:

arima_model_mensal <- auto.arima(tsMensalTrain)

Predição:

fcast_arima_4mth <- forecast(arima_model_mensal, h=mesesAPrever)
plot(fcast_arima_4mth, xlab="Anos", ylab="Fluxo Mensal")
lines(tsMensalTest4mth, col="red")

plot of chunk unnamed-chunk-39

Acurácia:

accuracy(fcast_arima_4mth, tsMensalTest4mth)
##                ME  RMSE  MAE     MPE  MAPE   MASE      ACF1 Theil's U
## Training set  145 10236 7610 -0.0156 1.595 0.2052 -0.005073        NA
## Test set     2173 10234 8719  0.2861 1.276 0.2351 -0.511317    0.1839

Para 6 meses

mesesAPrever <- 6

Predição:

fcast_arima_6mth <- forecast(arima_model_mensal, h=mesesAPrever)
plot(fcast_arima_6mth, xlab="Anos", ylab="Fluxo Mensal")
lines(tsMensalTest6mth, col="red")

plot of chunk unnamed-chunk-42

Acurácia:

accuracy(fcast_arima_6mth, tsMensalTest6mth)
##                ME  RMSE  MAE     MPE  MAPE   MASE      ACF1 Theil's U
## Training set  145 10236 7610 -0.0156 1.595 0.2052 -0.005073        NA
## Test set     3437  9902 8148  0.4719 1.181 0.2197 -0.352187    0.2011

Método ARIMA em prospecções de longo prazo

Para 1 ano

mesesAPrever <- 12

Predição:

fcast_arima_1yr <- forecast(arima_model_mensal, h=mesesAPrever)
plot(fcast_arima_1yr)
lines(tsMensalTest1yr, col="red")

plot of chunk unnamed-chunk-45

Acurácia:

accuracy(fcast_arima_1yr, tsMensalTest1yr)
##                 ME  RMSE   MAE     MPE  MAPE   MASE      ACF1 Theil's U
## Training set   145 10236  7610 -0.0156 1.595 0.2052 -0.005073        NA
## Test set     22409 31001 24765  2.9237 3.278 0.6677  0.697780    0.7174

Método ARIMA - Conclusões

Modelo Exponential Smoothing

Algo sobre.

ets() sem parâmetros determina automaticamente.

Ver (R. J. Hyndman and Athanasopoulos 2013). O autor possui um livro exclusivamente sobre o assunto em (R. Hyndman et al. 2008).

Método Exponential Smoothing em Curto Prazo

diasAPrever <- 30

Modelo:

etsDiario <- ets(tsDiarioTrain)
## Warning: I can't handle data with frequency greater than 24. Seasonality
## will be ignored. Try stlf() if you need seasonal forecasts.

Prospecção:

fcastDiario30days <- forecast(etsDiario, h=diasAPrever)

Comparar predição com valores reais do conjunto de teste:

plot(fcastDiario30days, xlab="Anos", ylab="Fluxo Mensal");
lines(tsDiarioTest30Days, col="red")
legend("topleft",legend=c("Real"),col=2,lty=1)

plot of chunk unnamed-chunk-50

Acurácia:

accuracy(fcastDiario30days, tsDiarioTest30Days)
##                   ME RMSE  MAE     MPE MAPE   MASE   ACF1 Theil's U
## Training set   87.87 1489 1265 -0.1499  6.7 0.6742 0.3239        NA
## Test set     -676.63 1736 1252 -3.6038  6.0 0.6672 0.4432     1.013

Método Exponential Smoothing em Médio Prazo

Para 6 meses

mesesAPrever <- 6

Modelo:

etsMensal <- ets(tsMensalTrain)

Prospecção:

fcastMensal6mth <- forecast(etsMensal, h=mesesAPrever)

Comparar predição com valores reais do conjunto de teste:

plot(fcastMensal6mth, xlab="Anos", ylab="Fluxo Mensal");
lines(tsMensalTest6mth, col="red")
legend("topleft",legend=c("Real"),col=2,lty=1)

plot of chunk unnamed-chunk-55

Acurácia:

accuracy(fcastMensal6mth, tsMensalTest6mth)
##                ME  RMSE   MAE    MPE  MAPE   MASE      ACF1 Theil's U
## Training set  910  8952  6764 0.1729 1.438 0.1824 -0.005476        NA
## Test set     4511 10353 10213 0.6550 1.495 0.2753  0.152408    0.1901

Método Exponential Smoothing em Longo Prazo

Para 1 ano

mesesAPrever <- 12

Prospecção:

fcastMensal1yr <- forecast(etsMensal, h=mesesAPrever)

Comparar predição com valores reais do conjunto de teste:

plot(fcastMensal1yr);
lines(tsMensalTest1yr, col="red")
legend("topleft",legend=c("Real"),col=2,lty=1)

plot of chunk unnamed-chunk-59

Acurácia:

accuracy(fcastMensal1yr, tsMensalTest1yr)
##                 ME  RMSE   MAE    MPE  MAPE   MASE      ACF1 Theil's U
## Training set   910  8952  6764 0.1729 1.438 0.1824 -0.005476        NA
## Test set     21648 29250 24499 2.8481 3.268 0.6605  0.789771    0.6718

Referências

Hyndman, Rob J. 2014. “Forecasting Time Series Using R.” http://robjhyndman.com/talks/MelbourneRUG.pdf.

Hyndman, Rob J, and George Athanasopoulos. 2013. Forecasting: principles and Practice. OTexts.

Hyndman, Rob, Anne B. Koehler, J. Keith Ord, and Ralph D. Snyder. 2008. Forecasting with Exponential Smoothing: The State Space Approach (Springer Series in Statistics). 2008th ed. Springer. http://amazon.com/o/ASIN/3540719164/.

Leek, Jeffrey. 2014. “Practical Machine Learning - Lecture 27 - Forecasting.” Johns Hopkins Bloomberg School of Public Health. https://d396qusza40orc.cloudfront.net/predmachlearn/027forecasting.pdf.